package com.topnav.mc.admin.service.impl;

import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.js.lib.cache.Cache;
import com.js.lib.cache.SysCache;
import com.topnav.mc.admin.bean.cachebean.CacheFencePolygonBean;
import com.topnav.mc.admin.bean.cachebean.CacheOrgBean;
import com.topnav.mc.admin.dao.mapper.DeviceMapper;
import com.topnav.mc.admin.entity.*;
import com.topnav.mc.admin.entity.bean.DeviceBean;
import com.topnav.mc.admin.entity.bean.FenceBean;
import com.topnav.mc.admin.entity.bean.LogContentBean;
import com.topnav.mc.admin.entity.bean.OrganizationBean;
import com.topnav.mc.admin.entity.enums.EnumLogType;
import com.topnav.mc.admin.entity.enums.EnumOperateFunction;
import com.topnav.mc.admin.entity.param.DeviceParam;
import com.topnav.mc.admin.entity.param.FenceParam;
import com.topnav.mc.admin.entity.param.OrganizationParam;
import com.topnav.mc.admin.security.PermissionGrade;
import com.topnav.mc.admin.service.*;
import com.topnav.mc.base.mc.McServiceImpl;
import com.topnav.mc.common.Constant;
import com.topnav.mc.common.SysConfigKeyConstant;
import com.topnav.mc.document.entity.Document;
import com.topnav.mc.document.service.IDocumentService;
import com.topnav.mc.exception.ExceptionMsg;
import com.topnav.mc.uitls.ExceptionUtil;
import com.topnav.mc.uitls.PermissionGradeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.js.lib.exception.CustomException;
import com.topnav.mc.admin.dao.mapper.OrganizationMapper;

import javax.annotation.Resource;

/**
 * 说明：组织机构CURD管理
 * @类名: OrganizationServiceImpl
 * <p>
 *
 * </p>
 * @author   kenny
 * @Date	 2021年11月19日上午9:35:09
 */
@Service
//public class OrganizationServiceImpl extends ServiceImpl<OrganizationMapper,Organization> implements IOrganizationService{
public class OrganizationServiceImpl extends McServiceImpl<OrganizationMapper, Organization,
		OrganizationBean, OrganizationParam> implements IOrganizationService {

	@Autowired
	private IUserService userService;
	@Autowired
	private IUserOrganizaitonService userOrganizaitonService;
	@Autowired
	private IDeviceService deviceService;
	@Autowired
	private IDocumentService documentService;
	@Autowired
	private ISiteService siteService;
	@Resource(name="sysCache")
	private Cache sysCache;
	@Autowired
	private PermissionGradeUtil permissionGradeUtil;
	@Autowired
	private IOperateLogService operateLogService;
	@Autowired
	private IFenceService fenceService;

	@Override
	protected void afterSave(Organization entity){
		this.saveToCache(entity);
		operateLogService.saveLog(EnumLogType.ADD, EnumOperateFunction.ORGANIZATION,new LogContentBean().setCode(entity.getCode()).setName(entity.getName()));
	};
	protected void afterUpdate(Organization entity){
		this.saveToCache(entity);
		operateLogService.saveLog(EnumLogType.EDIT, EnumOperateFunction.ORGANIZATION,new LogContentBean().setCode(entity.getCode()).setName(entity.getName()));
	};

	protected void afterDelete(Organization entity){
		this.removeFromCache(entity.getId());
		//更新父级的是否含子件的标志
		if (entity.getParentId() != null)
			this.updateParentHasChildTag(entity.getParentId());
		operateLogService.saveLog(EnumLogType.DELETE, EnumOperateFunction.ORGANIZATION,new LogContentBean().setCode(entity.getCode()).setName(entity.getName()));
	};

	@Override
	public boolean beforeDelete(Organization entity){
		// 1、是否有下级
		LambdaQueryWrapper<Organization> wrapper = new LambdaQueryWrapper<Organization>().eq(Organization::getParentId,entity.getId());
		if (this.getOne(wrapper,false) != null){
			//此机构已包含下级，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_OGRANIZATION_USED_BY_ORGANIZATION);

		}
		// 2、用户
		LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<User>()
				.eq(User::getOrgId,entity.getId());
				//.or()
				//.eq(User::getLoginOrgId,entity.getId());
		if (userService.getOne(userQueryWrapper,false) != null){
			//此机构已被注册的用户使用，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_OGRANIZATION_USED_BY_USER);
		}
		// 3、设备
		LambdaQueryWrapper<Device> deviceQueryWrapper = new LambdaQueryWrapper<Device>().eq(Device::getOrgId,entity.getId());
		if (deviceService.getOne(deviceQueryWrapper,false) != null){
			//此机构已被注册的设备使用，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_OGRANIZATION_USED_BY_DEVICE);
		}
		//4、文件
		LambdaQueryWrapper<Document> documentQueryWrapper = new LambdaQueryWrapper<Document>().eq(Document::getOrgId,entity.getId());
		if (documentService.getOne(documentQueryWrapper,false) != null){
			//此机构已被视频文件使用，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_OGRANIZATION_USED_BY_DOCUMENT);
		}

		//5、采集站
		LambdaQueryWrapper<Site> siteQueryWrapper = new LambdaQueryWrapper<Site>().eq(Site::getOrgId,entity.getId());
		if (siteService.getOne(siteQueryWrapper,false) != null){
			//此机构已被注册的采集站使用，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_OGRANIZATION_USED_BY_SITE);
		}


/*		LambdaQueryWrapper<UserOrganizaiton> userOrganizaitonQueryWrapper = new LambdaQueryWrapper<UserOrganizaiton>()
				.eq(UserOrganizaiton::getOrgId,entity.getId());
		if (userOrganizaitonService.getOne(userOrganizaitonQueryWrapper,false) != null){
			//此机构已被注册的用户使用，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_OGRANIZATION_USED_BY_USER);
		}*/


/*		LambdaQueryWrapper<Fence> fenceQueryWrapper = new LambdaQueryWrapper<Fence>().eq(Fence::getOrgId,entity.getId());
		if (siteService.getOne(siteQueryWrapper,false) != null){
			//此机构已被围栏使用，不能删除
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_DELETE_OGRANIZATION_USED_BY_FENCE);
		}*/
		return true;
	}
	/**
	 * 检查下级关系冲突,返回true为正确,没有冲突
	 * @param parentOrg
	 * @param curOrg
	 * @return
	 */
	private boolean checkEndlessLoop(Organization parentOrg, Organization curOrg ){
		boolean result = true;
		if (parentOrg == null){	return result;}
		if (parentOrg.getId() == curOrg.getId()){return false;}

		QueryWrapper<Organization> wrapper = new QueryWrapper<Organization>().eq("parent_id",curOrg.getId());
		List<Organization> orgs = this.list(wrapper);
		/** 如果没下级了不再继续检查 */
		if (CollectionUtils.isEmpty(orgs)){	return result;	}

		for (int i=0;i<orgs.size();i++){
			if (orgs.get(i).getId() == parentOrg.getId()){
				result = false;
				break;
			}

			//递归查找
			result = checkEndlessLoop(parentOrg,orgs.get(i));
			if (result == false){
				return result;
			}
		}
		return result;
	}
	@Override
	public List<Organization> fingAllOrgByUser(Long userId) {
		return getBaseMapper().fingAllOrgByUser(userId);
	}
	@Override
	public List<Object> genOrgOfLoginUser(User user) {
		List<Object> objectList = new ArrayList<>();
/*
		QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq("login_name",loginName);
		User user = userService.getOne(queryWrapper,false);
		if (user == null){return objectList;}*/

		/** 取得单位列表 */
		List<Organization> organizationList = this.fingAllOrgByUser(user.getId());
		if (user.getLoginOrgId() != null){
			/** 本登录单位排第一 */
/*			for(Organization organization : organizationList){
				if (user.getLoginOrgId().equals(organization.getId())){
					Map<String,Object> objectMap = new HashMap<>();
					objectMap.put("code",organization.getCode());
					objectMap.put("shortName",organization.getShortName());
					objectMap.put("disabled",true);
					objectMap.put("selected",true);
					objectList.add(objectMap);
					break;
				}
			}*/
			/** 其它单排后面 */
			for(Organization organization : organizationList){
				if (user.getLoginOrgId().equals(organization.getId())) {
					continue;
				}
				Map<String,Object> objectMap = new HashMap<>();
				objectMap.put("code",organization.getCode());
				objectMap.put("shortName",organization.getShortName());
				objectMap.put("disabled",false);
				objectMap.put("selected",false);
				objectList.add(objectMap);
			}
		}
		return objectList;
	}
	/**
	 * 取上级单位的信息
	 * @param orgList
	 */
	private List<Organization> getExtentProp(List<Organization> orgList){
		return orgList;
/*
		List<Long> ids = new ArrayList<Long>();
		for(Organization o : orgList){
			if (o.getParentId() != null){
				ids.add(o.getParentId());
			}
		}
		if (ids.size() > 0){
			List<Organization>  list = this.getBaseMapper().selectBatchIds(ids);
			for (Organization o : list){
				for(Organization origin : orgList){
					if (o.getId().equals(origin.getParentId())){
						origin.setParentCode(o.getCode());
						origin.setParentName(o.getShortName());
						origin.setParent(o);
					}
				}
			}
		}
		return orgList;*/
	}


	@Override
	public List<Organization> list(Wrapper<Organization> queryWrapper) {
		List<Organization> list = getBaseMapper().selectList(queryWrapper);
		/** 上级单位 */
		List<Organization> resultList = getExtentProp(list);
		return list;

	}
	/**
	 * 翻页查询
	 *
	 * @param page         翻页对象
	 * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
	 */
	@Override
	public <E extends IPage<Organization>> E page(E page, Wrapper<Organization> queryWrapper) {
		QueryWrapper<Organization> wrapper = new QueryWrapper<Organization>();
		if (queryWrapper.getEntity() != null) {

			if (!StringUtils.isEmpty(queryWrapper.getEntity().getCode())) {
				wrapper.like("code", queryWrapper.getEntity().getCode());
			}
			if (!StringUtils.isEmpty(queryWrapper.getEntity().getName())) {
				wrapper.like("name", queryWrapper.getEntity().getName());
			}

			if (queryWrapper.getEntity().getParentId() != null) {
				wrapper.eq("parent_id", queryWrapper.getEntity().getParentId());
			} else {
				wrapper.isNull("parent_id");
			}
		}else{
			wrapper.isNull("parent_id");
		}
		page = getBaseMapper().selectPage(page, wrapper);
		Organization o1;

		/** 上级单位 */
		page.setRecords(getExtentProp(page.getRecords()));
		return page;
	}

	@Override
	public boolean remove(Wrapper<Organization> queryWrapper) {
		return super.remove(queryWrapper);
	}
	/**
	 * 删除相关联
	 * 用户单位/用户登录单位/围栏
	 * @param entity
	 */
	@Override
	public void removeRelate(Organization entity){
		//1、机构用户
		userOrganizaitonService.remove(new LambdaQueryWrapper<UserOrganizaiton>().eq(UserOrganizaiton::getOrgId,entity.getId()));

		//2、用户单位登录, 把登录用户的单位改为 null
		userService.update(new LambdaUpdateWrapper<User>().set(User::getLoginOrgId,null).eq(User::getLoginOrgId,entity.getId()));
		//3、围栏
		fenceService.remove(new LambdaQueryWrapper<Fence>().eq(Fence::getOrgId,entity.getId()));
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean save(Organization entity) {
		if (this.getOne(new QueryWrapper<Organization>().eq("code",entity.getCode()), true) != null){
			//throw new CustomException(-1,"组织机构 编码  %s 已存在",entity.getCode());
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_PARAM_CODE_EXISTS);
		}
		if (StringUtils.isEmpty(entity.getShortName())){
			entity.setShortName(entity.getName());
		}
		entity.setCreateTime(new Date());
		entity.setUpdateTime(new Date());
		entity.setHasChild(false);

        boolean result = SqlHelper.retBool(getBaseMapper().insert(entity));
        if (!result){return result;}

        //更新父级的是否含子件的标志
		this.updateParentHasChildTag(entity.getParentId());

        Organization parent = this.getOne(new QueryWrapper<Organization>().eq("id",entity.getParentId()==null?0L:entity.getParentId()), false);
        /** 检查冲突*/
        if (!checkEndlessLoop(parent,entity)){
        	//throw new CustomException(-1,"上级组织机构冲突, 先重新选择上级组织机构");
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_PARAM_DATA_CONFLICTS);
        }

        /** 更新 path */
    	if(parent != null){
    		entity.setPath(parent.getPath() + entity.getId()+"/");
    	}else{
    		entity.setPath(entity.getId()+"/");
    	}

    	this.updateById(entity);
        return true;
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean updateById(Organization entity) {
		boolean result = false;
		QueryWrapper<Organization> wrapper = new QueryWrapper<Organization>()
				.eq("code", entity.getCode()).ne("id", entity.getId());
		if (this.getOne(wrapper, false) != null){
			//throw new CustomException(-1,"组织机构编码  %s 已存在",entity.getCode());
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_PARAM_CODE_EXISTS);
		}

        Organization parent = this.getOne(new QueryWrapper<Organization>().eq("id",entity.getParentId()==null?0L:entity.getParentId()), false);
        /** 检查冲突*/
        if (!checkEndlessLoop(parent,entity)){
        	//throw new CustomException(-1,"上级组织机构冲突");
			throw ExceptionUtil.commonException(ExceptionMsg.ERROR_PARAM_DATA_CONFLICTS);
        }

		/** 先保留原数据  */
		Organization oldOrg = this.getById(entity.getId());
		/** 更新 */
		entity.setUpdateTime(new Date());
		result = super.updateById(entity);
		if (!result){return false;}

		if (null == entity.getParentId()) {
			UpdateWrapper<Organization> updateWrapper = new UpdateWrapper<Organization>();
			updateWrapper.set("parent_id", null);
			updateWrapper.eq("id", entity.getId());
			 this.update(updateWrapper);
		}

		/** 如果修改了上级，则一起更新 path */
		Long oldParentId = oldOrg.getParentId()==null?0L:oldOrg.getParentId();
		Long newParentId = entity.getParentId()==null?0L:entity.getParentId();
		if (!oldParentId.equals(newParentId)){
			if (newParentId.equals(0L)){
				entity.setPath(entity.getId() + "/");
			}else{
				entity.setPath(this.getById(newParentId).getPath() + entity.getId() + "/");
			}

			wrapper.clear();
			wrapper.likeRight("path", oldOrg.getPath());
			List<Organization> list = this.list(wrapper);
			for (Organization o : list){
				String path = o.getPath().replaceFirst(oldOrg.getPath(),entity.getPath());
				o.setPath(path);
			}
			this.updateBatchById(list);
		}
		//更新父级的是否含子件的标志
		this.updateParentHasChildTag(entity.getParentId());
		this.updateParentHasChildTag(oldOrg.getParentId());
		return true;
	}

	/**
	 * 更新父级的是否含子件的标志
	 * @param id
	 */
	private void updateParentHasChildTag(Long id){
		if (id != null){
			QueryWrapper<Organization> wrapper = new QueryWrapper<>();
			wrapper.eq("parent_id",id);
			Organization tempOrg = this.getOne(wrapper,false);
			UpdateWrapper<Organization> updateWrapper = new UpdateWrapper<>();
			updateWrapper.eq("id",id);
			if (tempOrg == null){
				updateWrapper.set("has_child",false);
			}else{
				updateWrapper.set("has_child",true);
			}
			this.update(updateWrapper);
		}
	}

	/**
	 * 保存到缓存
	 */
	private final String orgCacheKey = "org_cache_key";
	@Override
	public void saveToCache(Organization organization){
		CacheOrgBean cacheOrgBean = new CacheOrgBean();
		cacheOrgBean.setId(organization.getId());
		cacheOrgBean.setPath(organization.getPath());
		sysCache.hset(this.orgCacheKey,organization.getId().toString(),cacheOrgBean);
	}
	@Override
	public void saveAllToCache(){
		sysCache.del(this.orgCacheKey);
		List<Organization> list = this.list();
		for(Organization organization : list){
			this.saveToCache(organization);
		}
	}
	@Override
	public void removeFromCache(Long orgId){
		sysCache.hdel(this.orgCacheKey,orgId);
	}

	/**
	 * 从缓存取设备
	 */
	@Override
	public CacheOrgBean getFromCache(Long orgId){
		return (CacheOrgBean)sysCache.hget(this.orgCacheKey,orgId.toString());
	}
	@Override
	public List<CacheOrgBean> getAllFromCache(){
		Map<Object,Object> map = sysCache.hmget(this.orgCacheKey);
		List<CacheOrgBean> result = new ArrayList<CacheOrgBean>();
		if (map != null) {
			for (Object obj : map.values()) {
				result.add((CacheOrgBean) obj);
			}
		}
		return result;
	}

}
